package com.lmxdawn.api.dnf.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lmxdawn.api.admin.entity.GoldCoin;
import com.lmxdawn.api.admin.service.IGoldCoinService;
import com.lmxdawn.api.common.enums.ResultEnum;
import com.lmxdawn.api.common.exception.NotRealnameException;
import com.lmxdawn.api.common.res.BaseResponse;
import com.lmxdawn.api.common.session.SessionContextHolder;
import com.lmxdawn.api.common.session.SessionHelper;
import com.lmxdawn.api.common.session.TokenHelper;
import com.lmxdawn.api.common.session.UserSession;
import com.lmxdawn.api.common.util.ResultVOUtils;
import com.lmxdawn.api.dnf.dto.CommonReq;
import com.lmxdawn.api.dnf.dto.OrderDTO;
import com.lmxdawn.api.dnf.entity.Order;
import com.lmxdawn.api.dnf.entity.OrderItem;
import com.lmxdawn.api.dnf.service.OrderItemService;
import com.lmxdawn.api.dnf.service.OrderService;
import com.lmxdawn.api.dnf.util.GoldTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

@RestController
@CrossOrigin
@Slf4j
@RequestMapping("/web/dnf/mall/order")
public class OrderController {

    @Resource
    private OrderService orderService;

    @Resource
    OrderItemService orderItemService;

    @Resource
    IGoldCoinService goldCoinService;
    @Resource
    RedissonClient redissonClient;

    /**
     * 查询全部数据
     *
     * @return
     */
    @GetMapping
    public BaseResponse<List<Order>> findAll() {
        List<Order> orderList = orderService.findAll();
        return ResultVOUtils.success(orderList);
    }
    /***
     * 根据ID查询数据
     * @param id
     * @return
     */
    @GetMapping("/list")
    public BaseResponse<Page<Order>> listAll(@RequestParam Long page,
                                             HttpServletRequest request,
                                             @RequestParam(value = "id", required = false) String id,
                                             @RequestParam(value = "status", required = false) String status) {
        String userId = SessionContextHolder.get().getId();
        Page<Order> orderPage = new Page<>(page, 10);
        Page<Order> order = orderService.page(orderPage,
                Wrappers.<Order>lambdaQuery()
                        .and(w->
                                w.eq(Order::getUserId, userId)
                                .or()
                                .eq(Order::getSaleId, userId)
                        )
                        .eq(StrUtil.isNotBlank(id), Order::getId, id)
                        .eq(StrUtil.isNotBlank(status)
                                && !status.equals("0"), Order::getStatus, status)
                        .ne(Order::getStatus, 4)
                        .ne(Order::getStatus, -1)
                        .orderByDesc(Order::getCreateTime)
        );
        if (CollUtil.isEmpty(order.getRecords())){
            return ResultVOUtils.success(order);
        }
        String tokenValue = TokenHelper.getTokenValue(request);
        UserSession userSession = SessionHelper.getSessionStrategy().getUserSession(tokenValue);
        Set<String> collect = order.getRecords().stream().map(Order::getId).collect(Collectors.toSet());
        List<OrderItem> orderItems = orderItemService.queryByOrderIdIn(collect);
        Map<String, List<OrderItem>> orderItemMap = orderItems.stream().collect(Collectors.groupingBy(OrderItem::getOrderId));
//        List<GoldCoin> list = goldCoinService.list();
        order.getRecords().forEach(o->{
            List<OrderItem> orderItems1 = orderItemMap.get(o.getId());
            o.setOrderItems(orderItems1);
//            if (StrUtil.isNotBlank(id)){
//                Map<Long, GoldCoin> coinMap = list.stream().collect(Collectors.toMap(GoldCoin::getId, Function.identity()));
//                StringBuilder sb = new StringBuilder();
//                if (StrUtil.isNotBlank(o.getGameServer())){
//                    sb.append(o.getGameServer());
//                    sb.append(" : ");
//                }
//                orderItems1.forEach(item->{
//                    GoldCoin goldCoin = coinMap.get(item.getProductId());
//                    if (goldCoin == null){
//                        return;
//                    }
//                    GoldTypeEnum typeEnum = goldCoin.getType() == null ? null : GoldTypeEnum.match(goldCoin.getType());
//                    sb.append(typeEnum == null ? "" : typeEnum.getLabel() );
//                    sb.append(" : ");
//                    sb.append(item.getPrice());
//                    sb.append("(万金/元)");
//                    sb.append(" * ");
//                    sb.append(item.getQuantityOrder());
//                });
                o.setItemDesc(o.getRemark());
//            }
            o.setProp((o.getSaleId() != null && StrUtil.equals(o.getSaleId(), userId))? "2": "1");
            o.setUnreadCount(orderService.countMessage(o.getId()+"",userSession.getId()+""));
        });
        return ResultVOUtils.success(order);
    }


    /***
     * 根据ID查询数据
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public BaseResponse<Order> findById(@PathVariable String id) {
        Order order = orderService.findById(id);
        return ResultVOUtils.success(order);
    }

    @GetMapping("/status/{id}")
    public BaseResponse<Order> getById(@PathVariable String id) {
        Order order = orderService.getById(id);
        return ResultVOUtils.success(order);
    }

    /***
     * 根据ID查询数据
     * @param id
     * @return
     */
    @PostMapping("/delete/{id}")
    public BaseResponse<Order> remove(@PathVariable String id) {
        orderService.lambdaUpdate(). eq(Order::getId, id)
                .set(Order::getUpdateTime, DateUtil.date())
                .set(Order::getStatus, 4).update();
        return ResultVOUtils.success();
    }


    /***
     * 修改数据
     * @param commonReq
     * @param id
     * @return
     */
    @PutMapping(value = "/{id}")
    public BaseResponse update(@RequestBody CommonReq<Order> commonReq, @PathVariable String id) {
        Order content = commonReq.getContent();
        content.setId(id);
        orderService.update(content);
        return ResultVOUtils.success();
    }

//    /***
//     * 根据ID删除订单
//     * @param id
//     * @return
//     */
//    @DeleteMapping(value = "/{id}")
//    public BaseResponse delete(@PathVariable String id) {
//        orderService.delete(id);
//        return ResultVOUtils.success();
//    }

    /***
     * 生成订单
     * @param commonReq
     * @return
     */
    @PostMapping("/generateOrder")
    public BaseResponse generateOrder(@RequestBody CommonReq<OrderDTO> commonReq) {
        OrderDTO orderDTO = commonReq.getContent();
        if (!SessionContextHolder.get().isRealName()) {
            throw new NotRealnameException();
        }
        // todo 锁 以及对所有的订单相关操作都要加锁
        // 这里锁的维度是什么 ? 商品id? 防止超卖 用户id 防止重复操作
        RLock productLock = redissonClient.getLock(String.format("ORDER_LOCK_%s", orderDTO.getProductId()));
        RLock userLock = redissonClient.getLock(String.format("ORDER_LOCK_%s", orderDTO.getProductId()));
        if (!productLock.tryLock() || !userLock.tryLock()){
            throw new RuntimeException("系统繁忙");
        }
        try {
            String userId = SessionContextHolder.getId();
            String orderId = orderService.generateOrder(orderDTO,userId);
            BaseResponse response = ResultVOUtils.success(orderId);
            log.info("============>generateOrder:{}->{}", JSON.toJSON(commonReq.getContent()), JSON.toJSON(response));
            return response;
        } catch (Exception e) {
            return ResultVOUtils.error(ResultEnum.ORDER_FAILED, e.getMessage());
        }finally {
            productLock.unlock();
            userLock.unlock();
        }

    }

}
